package com.gr.jron.service.impl;

import com.gr.jron.dao.GenericDao;
import com.gr.jron.dao.UserDao;
import com.gr.jron.model.*;
import com.gr.jron.service.UserExistsException;
import com.gr.jron.service.UserManager;
import com.gr.jron.service.UserService;
import com.gr.jron.util.PaginationSupport;
import com.gr.jron.util.ServletTools;
import net.sf.json.JSONObject;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.springframework.dao.DataIntegrityViolationException;

import javax.jws.WebService;
import javax.persistence.EntityExistsException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Implementation of UserManager interface.
 *
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 */
@WebService(serviceName = "UserService", endpointInterface = "com.gr.jron.service.UserService")
public class UserManagerImpl extends UniversalManagerImpl implements UserManager, UserService {
    private UserDao dao;
    private GenericDao<UgGovermentInfo, Long> govermentInfoDao;
    private GenericDao<UgTeamInfo, Long> teamInfoDao;
    private GenericDao<UgPersonInfo, Long> personInfoDao;
    private GenericDao<UgCompanyInfo, Long> companyInfoDao;

    public void setGovermentInfoDao(GenericDao<UgGovermentInfo, Long> govermentInfoDao) {
        this.govermentInfoDao = govermentInfoDao;
    }

    public void setTeamInfoDao(GenericDao<UgTeamInfo, Long> teamInfoDao) {
        this.teamInfoDao = teamInfoDao;
    }

    public void setPersonInfoDao(GenericDao<UgPersonInfo, Long> personInfoDao) {
        this.personInfoDao = personInfoDao;
    }

    public void setCompanyInfoDao(GenericDao<UgCompanyInfo, Long> companyInfoDao) {
        this.companyInfoDao = companyInfoDao;
    }

    /**
     * Set the Dao for communication with the data layer.
     *
     * @param dao the UserDao that communicates with the database
     */
    public void setUserDao(UserDao dao) {
        this.dao = dao;
    }

    /**
     * {@inheritDoc}
     */
    public User getUser(String userId) {
        return dao.get(new Long(userId));
    }

    /**
     * {@inheritDoc}
     */
    public List<User> getUsers(User user) {
        return dao.getUsers(user);
    }

    /**
     * {@inheritDoc}
     */
    public User saveUser(User user) throws UserExistsException {
        // if new user, lowercase userId
        if (user.getVersion() == null) user.setUsername(user.getUsername().toLowerCase());
        try {
            return dao.saveUser(user);
        } catch (DataIntegrityViolationException e) {
            e.printStackTrace();
            log.warn(e.getMessage());
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        } catch (EntityExistsException e) { // needed for JPA
            e.printStackTrace();
            log.warn(e.getMessage());
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        }
    }

    public User saveUser(User user, UgGovermentInfo govermentInfo) throws UserExistsException {
        UgGovermentInfo goverment = govermentInfoDao.save(govermentInfo);
        user.setUgGovermentInfo(goverment);
        return saveUser(user);
    }

    public User saveUser(User user, UgTeamInfo teamInfo) throws UserExistsException {
        UgTeamInfo team = teamInfoDao.save(teamInfo);
        user.setUgTeamInfo(team);
        return saveUser(user);
    }

    public User saveUser(User user, UgPersonInfo personInfo) throws UserExistsException {
        UgPersonInfo person = personInfoDao.save(personInfo);
        user.setUgPersonInfo(person);
        return saveUser(user);
    }

    public User saveUser(User user, UgCompanyInfo companyInfo) throws UserExistsException {
        UgCompanyInfo company = companyInfoDao.save(companyInfo);
        user.setUgCompanyInfo(company);
        return saveUser(user);
    }

    /**
     * {@inheritDoc}
     */
    public void removeUser(String userId) {
        log.debug("removing user: " + userId);
        dao.remove(new Long(userId));
    }

    /**
     * {@inheritDoc}
     *
     * @param username the login name of the human
     * @return User the populated user object
     * @throws UsernameNotFoundException thrown when username not found
     */
    public User getUserByUsername(String username) throws UsernameNotFoundException {
        return (User) dao.loadUserByUsername(username);
    }

    public User getUserByName(String username) {
        List<User> users = dao.findByProperty("username", username);
        if (users == null || users.isEmpty()) return null;
        else return users.get(0);
    }

    public User getUserByEmail(String email) {
        List<User> users = dao.findByProperty("email", email);
        if (users == null || users.isEmpty()) return null;
        else return users.get(0);
    }

    //Setting params callback => [ stcCallback1015 ] limit => [ 1 ] start => [ 1 ] sort => [ email ]
    // filterTxt => [ Choose Filter ] ajax => [ true ] filterValue => [  ] _dc => [ 1192090842262 ] dir => [ DESC ]
    public JSONObject getJsonUsersPerPage(PagingQuery pq) {
        Map conditions = new HashMap();
        if (!"jron".equals(pq.getFilterTxt()) && pq.getFilterValue().length() > 0)
            conditions.put(pq.getFilterTxt(), pq.getFilterValue());
        boolean dir = pq.getDir().toLowerCase().trim().equals("asc");

        PaginationSupport ps = dao.findPageByCriteria(pq.getLimit(), pq.getStart(), dir, pq.getSort(), conditions);

        List<User> users = ps.getItems();
        for (User user : users) {
            forExtJsonreader(user);
        }
        int count = ps.getTotalCount();
        return ServletTools.jsonExtGridBackendReturn(users, count);
    }

    public JSONObject getJsonUser(String id) {
        User user = dao.get(Long.valueOf(id));
        forExtJsonreader(user);
        return JSONObject.fromObject(user, ServletTools.hibernateJsonConfig());
    }

    private void forExtJsonreader(User user) {
        switch (user.getUserGroup()) {
            case COMPANY:
                user.setUgGovermentInfo(new UgGovermentInfo());
                user.setUgPersonInfo(new UgPersonInfo());
                user.setUgTeamInfo(new UgTeamInfo());
                break;
            case PERSON:
                user.setUgCompanyInfo(new UgCompanyInfo());
                user.setUgGovermentInfo(new UgGovermentInfo());
                user.setUgTeamInfo(new UgTeamInfo());
                break;
            case TEAM:
                user.setUgCompanyInfo(new UgCompanyInfo());
                user.setUgGovermentInfo(new UgGovermentInfo());
                user.setUgPersonInfo(new UgPersonInfo());
                break;
            case GOVERMENT:
                user.setUgPersonInfo(new UgPersonInfo());
                user.setUgTeamInfo(new UgTeamInfo());
                user.setUgCompanyInfo(new UgCompanyInfo());
                break;
            case OPERATION:
                user.setUgPersonInfo(new UgPersonInfo());
                user.setUgTeamInfo(new UgTeamInfo());
                user.setUgCompanyInfo(new UgCompanyInfo());
                user.setUgGovermentInfo(new UgGovermentInfo());
                break;
        }
    }

}
